﻿using CodeGenerator.CodeGenBL;
using CodeGenerator.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using CodeGenerator.ProjectBL;
using CodeGenerator.Util;
using CodeGenerator.Template;
using ClassModelDto = CodeGenerator.Models.ClassModel;

namespace CodeGenerator.Generator
{
    public class BLGenerator : GenerateBase
    {
        public BLGenerator(IProjectBL projectBL, ICodeGenBL codeGenBL, String outputPath)
            : base(projectBL, codeGenBL, outputPath)
        {
        }

        public override void Generate(int projectId)
        {
            var classDto = this.CodeGenBL.GetClassByProjectId(new CodeGenBL.ProjectPkDto { ProjectId = projectId });
            var projectDto = this.ProjectBL.GetProject(new ProjectBL.ProjectPkDto { ProjectId = projectId });

            if (projectDto.Status && classDto.Status)
            {
                if (projectDto.Data != null && classDto.Data != null)
                {
                    //ClassModel classModel = new ClassModel(classDto.Data[0]);
                    ProjectModel projectModel = new ProjectModel(projectDto.Data);
                    List<ClassModel> classModel = new List<ClassModelDto>();
                    foreach (var dto in classDto.Data)
                    {
                        classModel.Add(new ClassModel(dto));
                    }
                    MetaData modelForBL = new MetaData();
                    modelForBL.Models = classModel;
                    modelForBL.Project = projectModel;

                    List<LookupClassModel> LookupClass = new List<LookupClassModel>();
                    foreach (var myClass in modelForBL.Models)
                    {
                        foreach (var myAttr in myClass._attributes)
                        {
                            if (myAttr.DataType.Name == "Lookup Table")
                            {
                                var lookupDto = this.CodeGenBL.GetLookupClass(new CodeGenBL.AttributePkDto { Id = myAttr.Id });
                                if (lookupDto.Data != null)
                                {
                                    LookupClass.Add(new LookupClassModel(lookupDto.Data));

                                }
                            }
                        }
                    }

                    OutputPath = Path.Combine(OutputPath, new ProjectModel(projectDto.Data).ProjectName);
                    // Create Output Root Path if not exits (outputpath/projectname)
                    DirectoryExt.CreateIfMissing(OutputPath);
                    GenerateDto(modelForBL, LookupClass);
                    GenerateService(modelForBL, LookupClass);
                    GenerateProperties(modelForBL);
                }

            }
        }

        private void GenerateService(MetaData data, List<LookupClassModel> lookups)
        {
            //build metadata
            //var classDto = this.CodeGenBL.GetClassByProjectId(new CodeGenBL.ProjectPkDto { ProjectId = data.Project.ProjectId });
            //var projectDto = this.ProjectBL.GetProject(new ProjectBL.ProjectPkDto { ProjectId = data.Project.ProjectId });
            

            //var blConfig = new CodeGenerator.Template.Service.configBL();// configBL.tt
            //blConfig.Generate(this.OutputPath); //Generate Output 

            //var blInterfaceService = new CodeGenerator.Template.Service.InterfaceService(); //interfaceService.tt
            //blInterfaceService.Data.Models.Add(new ClassModel
            //{
            //    _attributes = new List<AttributeModel>()
            //});
            ////make PickupListModel data
            //blInterfaceService.Data = modelForBL;
            ////blInterfaceService.PickupData.Add();
            //blConfig.Generate(this.OutputPath);

            //var blService_svc_cs = new CodeGenerator.Template.Service.Service_svc_cs(); //service_svc_cs.tt
            //blService_svc_cs.Data.Models.Add(new ClassModel
            //{
            //    _attributes = new List<AttributeModel>()
            //});
            //blService_svc_cs.Data = modelForBL;
            //blService_svc_cs.Generate(this.OutputPath);

            //var blService_svc = new CodeGenerator.Template.Service.Service_svc(); //service_svc.tt
            //blService_svc.Data.Models.Add(new ClassModel
            //{
            //    _attributes = new List<AttributeModel>()
            //});
            //blService_svc.Data = modelForBL;
            //blService_svc.Generate(this.OutputPath);

            var ttFiles = Directory.GetFiles("Template/Service/", "*.tt", SearchOption.TopDirectoryOnly); //Get file tt ทั้งหมดใน Folder Template/Service/Dto/ns
            var dtoPath = OutputPath + @"/{ProjectName}.Service";
            foreach (var filepath in ttFiles)
            {
                var filename = Path.GetFileNameWithoutExtension(filepath);

                //Generate in Dto Folder
                var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName);//.Replace("{ClassName}", modelItem.Name);
                DirectoryExt.CreateIfMissing(destinationPath);
                var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.Service." + filename));
                dto.Data.Models = data.Models;
                dto.Data.Project = data.Project;
                dto.lookups = lookups;
                var filenameApplyFormat = dto.Filename.Replace("{ProjectName}", data.Project.ProjectName);
                var outputString = dto.TransformText();
                var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
                if (File.Exists(destinationFilePath))
                {
                    File.Delete(destinationFilePath);
                }

                File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));

            }

        }

        private void GenerateDto(MetaData data, List<LookupClassModel> lookups)
        {
            //var blDto = new CodeGenerator.Template.Service.Dto.ns.Dto();
            //blDto.Data = modelForBl;
            //blDto.Generate(this.OutputPath);

            //var blGetAllRequestDto = new CodeGenerator.Template.Service.Dto.ns.GetAllRequestDto();
            //blGetAllRequestDto.Data = modelForBl;
            //blGetAllRequestDto.Generate(this.OutputPath);

            //var blResponseDto = new CodeGenerator.Template.Service.Dto.ResponseDto();
            //blResponseDto.Data.Models.Add(new ClassModel
            //{
            //    _attributes = new List<AttributeModel>()
            //});
            //blResponseDto.Data = modelForBl;
            //blResponseDto.Generate(this.OutputPath);


            ////generate file ที่อยู่ภายใต้ folder ns โดยต้องสร้าง folder แยกตาม ClassModel
            //var ttFiles = Directory.GetFiles("Template/Service/Dto/ns", "*.tt", SearchOption.TopDirectoryOnly); //Get file tt ทั้งหมดใน Folder Template/Service/Dto/ns
            //var dtoPath = OutputPath + @"/{ProjectName}.Service/Dto/{ClassName}";
            //foreach (var filepath in ttFiles)
            //{
            //    var filename = Path.GetFileNameWithoutExtension(filepath);
            //    foreach (var modelItem in data.Models)
            //    {
            //        //Generate in Dto Folder
            //        var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName).Replace("{ClassName}", modelItem.Name);
            //        DirectoryExt.CreateIfMissing(destinationPath);
            //        var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.Service.Dto.ns." + filename)); //**** อันนี้ namespace ของ tt ต้องมีคำว่า ns ด้วย
            //        dto.Data.Models = new List<ClassModelDto> { modelItem };
            //        dto.Data.Project = data.Project;
            //        var filenameApplyFormat = dto.Filename.Replace("{ClassName}", modelItem.Name).Replace("{ProjectName}", data.Project.ProjectName);
            //        var outputString = dto.TransformText();
            //        var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
            //        if (File.Exists(destinationFilePath))
            //        {
            //            File.Delete(destinationFilePath);
            //        }

            //        File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));

            //    }
            //}

            
            //generate file ที่อยู่นอก folder ns โดยต้องไม่สร้าง folder แยกตาม ClassModel 
            var ttFiles = Directory.GetFiles("Template/Service/Dto/", "*.tt", SearchOption.TopDirectoryOnly); //Get file tt ทั้งหมดใน Folder Template/Service/Dto
            var dtoPath = OutputPath + @"/{ProjectName}.Service/Dto/";
            foreach (var filepath in ttFiles)
            {
                var filename = Path.GetFileNameWithoutExtension(filepath);
                //Generate in Dto Folder
                        var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName);
                        DirectoryExt.CreateIfMissing(destinationPath);
                if (filename.Equals("ResponseDto"))
                {
                    var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.Service.Dto." + filename));
                    dto.Data.Project = data.Project;
                    var filenameApplyFormat = dto.Filename;
                    var outputString = dto.TransformText();
                    var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
                    if (File.Exists(destinationFilePath))
                    {
                        File.Delete(destinationFilePath);
                    }

                    File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));
                }
                else
                {
                    foreach (var modelItem in data.Models)
                    {
                        var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.Service.Dto." + filename));
                        dto.Data.Models = new List<ClassModelDto> { modelItem };
                        dto.Data.Project = data.Project;
                        dto.lookups = lookups;
                        var filenameApplyFormat = dto.Filename.Replace("{ClassName}", modelItem.Name).Replace("{ProjectName}", data.Project.ProjectName);
                        var outputString = dto.TransformText();
                        var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
                        if (File.Exists(destinationFilePath))
                        {
                            File.Delete(destinationFilePath);
                        }

                        File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));

                    }
                }
            }
        }

        private void GenerateProperties(MetaData data)
        {
            //var blAssemblyInfo = new CodeGenerator.Template.Service.Service_svc(); //service_svc.tt
            //blAssemblyInfo.Data.Models.Add(new ClassModel
            //{
            //    _attributes = new List<AttributeModel>()
            //});
            //blAssemblyInfo.Data = modelForBL;
            ////blAssemblyInfo.Generate(this.OutputPath);


            var ttFiles = Directory.GetFiles("Template/Service/Properties/", "*.tt", SearchOption.TopDirectoryOnly);
            var dtoPath = OutputPath + @"/{ProjectName}.Service/Properties/";
            foreach (var filepath in ttFiles)
            {
                var filename = Path.GetFileNameWithoutExtension(filepath);
                //    foreach (var modelItem in data.Models)
                //    {
                //        //Generate in Dto Folder
                var destinationPath = dtoPath.Replace("{ProjectName}", data.Project.ProjectName);
                DirectoryExt.CreateIfMissing(destinationPath);
                var dto = (ITemplate)Activator.CreateInstance(Type.GetType("CodeGenerator.Template.Service.Properties." + filename));
                //        dto.Data.Models = new List<ClassModelDto> { modelItem };
                dto.Data.Models = data.Models;
                dto.Data.Project = data.Project;
                var filenameApplyFormat = dto.Filename.Replace("{ProjectName}", data.Project.ProjectName);
                
                var outputString = dto.TransformText();
                var destinationFilePath = destinationPath + "/" + filenameApplyFormat;
                if (File.Exists(destinationFilePath))
                {
                    File.Delete(destinationFilePath);
                }

                File.WriteAllText(destinationFilePath, outputString, Encoding.GetEncoding("UTF-8"));
                //    }
            }
        }
    }
}
